import 'package:boss/color_constant.dart';
import 'package:boss/textStyle/text_style.dart';
import 'package:hi_common/hi_common.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'dart:math' as math;

class CircleProgress extends StatefulWidget {
  final double radius;
  final double progress;

  const CircleProgress({
    Key key,
    this.radius,
    this.progress = 0.0,
  })  : assert(progress >= 0 && progress <= 1),
        super(key: key);

  @override
  _CircleProgressState createState() => _CircleProgressState();

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(DoubleProperty('radius', radius));
    properties.add(DoubleProperty('progress', progress));
  }
}

class _CircleProgressState extends State<CircleProgress> {
  @override
  Widget build(BuildContext context) {
    return _CircleProgressRenderObjectWidget(
      radius: widget.radius,
      progress: widget.progress,
    );
  }
}

class _CircleProgressRenderObjectWidget extends LeafRenderObjectWidget {
  final double radius;
  final double progress;

  const _CircleProgressRenderObjectWidget({
    this.radius,
    this.progress,
  });

  @override
  RenderObject createRenderObject(BuildContext context) {
    return _RenderCircleProgress(
      radius: radius,
      progress: progress,
    );
  }

  @override
  void updateRenderObject(BuildContext context, _RenderCircleProgress renderObject) {
    renderObject
      ..progress = progress
      ..radius = radius;
  }
}

class _RenderCircleProgress extends RenderBox {
  double _radius;
  double _progress;

  set radius(double value) {
    _radius = value;
    markNeedsLayout();
  }

  set progress(double value) {
    _progress = value;
    markNeedsPaint();
  }

  _RenderCircleProgress({
    double radius,
    double progress,
  })  : _radius = radius,
        _progress = progress;

  double get width {
    return _radius * 2;
  }

  double get angle {
    return math.pi / 180 * 360 * _progress;
  }

  double grooveWidth = 12.w;
  Color grooveColor = ColorConstant.f3f5fb;
  Color startColor = ColorConstant.f4997e9;
  Color endColor = ColorConstant.f282de8;

  //是否根据父布局进行约束
  @override
  bool get sizedByParent => true;

  @override
  void performResize() {
    size = Size(
      constraints.hasBoundedWidth ? constraints.maxWidth : width,
      constraints.hasBoundedHeight ? constraints.maxHeight : width,
    );
  }

  @override
  void paint(PaintingContext context, Offset offset) {
    final Canvas canvas = context.canvas;

    drawCircleGroove(canvas, offset);
    if (_progress != 0) drawCircleProgress(canvas, offset);
    drawDot(canvas, offset);
    drawInnerCircle(canvas, offset);
    drawPercentageText(canvas, offset);
  }

  //绘制背景进度凹槽
  drawCircleGroove(Canvas canvas, Offset offset) {
    final Paint paint = Paint()
      ..isAntiAlias = true
      ..style = PaintingStyle.stroke
      ..strokeWidth = grooveWidth
      ..color = grooveColor;

    canvas.drawCircle(offset + Offset(_radius, _radius), _radius - grooveWidth, paint);
  }

  //绘制进度条
  drawCircleProgress(Canvas canvas, Offset offset) {
    final gradientRect = new Rect.fromLTWH(0.0, 0.0, size.width, size.height);

    final gradient = new SweepGradient(
      endAngle: angle,
      tileMode: TileMode.clamp,
      colors: [startColor, endColor],
    );

    final Paint paint = Paint()
      ..isAntiAlias = true
      ..style = PaintingStyle.stroke
      ..strokeWidth = grooveWidth
      ..strokeCap = StrokeCap.round
      ..shader = gradient.createShader(gradientRect);

    final Rect rect = Rect.fromLTWH(
      offset.dx + grooveWidth,
      offset.dy + grooveWidth,
      width - grooveWidth * 2,
      width - grooveWidth * 2,
    );

    canvas.drawArc(rect, 0, angle, false, paint);
  }

  //绘制进度点
  drawDot(Canvas canvas, Offset offset) {
    double radius = 3.w;
    double strokeWidth = 6.w;

    final centerDot = offset + Offset(_radius, _radius);
    final dx = math.cos(angle) * (_radius - grooveWidth) + centerDot.dx;
    final dy = math.sin(angle) * (_radius - grooveWidth) + centerDot.dy;

    final paint = Paint()
      ..color = ColorConstant.f4997e9
      ..strokeWidth = strokeWidth
      ..style = PaintingStyle.stroke;

    canvas.drawCircle(Offset(dx, dy), radius, paint);

    final innerPainter = Paint()
      ..color = ColorConstant.f3f5fb
      ..strokeWidth = 0
      ..style = PaintingStyle.fill;

    canvas.drawCircle(Offset(dx, dy), radius, innerPainter);
  }

  //绘制内环
  drawInnerCircle(Canvas canvas, Offset offset) {
    double raidus = 70.w;

    final parent = Paint()
      ..color = ColorConstant.ff5770f6.withOpacity(0.2)
      ..strokeWidth = 1.px
      ..style = PaintingStyle.stroke;

    canvas.drawCircle(offset + Offset(_radius, _radius), raidus, parent);
  }

  //绘制百分数
  drawPercentageText(Canvas canvas, Offset offset) {
    TextPainter(
      textDirection: TextDirection.ltr,
      textAlign: TextAlign.center,
      text: TextSpan(text: ' ${(_progress * 100).toInt()}%\r\n', style: TextStyleConstant().blue_46, children: [
        TextSpan(text: '完成度', style: TextStyleConstant().normal_4_22),
      ]),
    )
      ..layout(maxWidth: width, minWidth: width)
      ..paint(
        canvas,
        offset + Offset(0, 57.w),
      );
  }
}
